import axios from 'axios'
import { Message, Modal } from 'view-design';
import { setCookie, getCookie } from '@/utils/common';
import errorCode from '@/utils/errorCode';
import store from '@/store'
import md5 from 'js-md5'
import router from '@/router';
let pending = {};// 网络请求记录map结构
let CancelToken = axios.CancelToken;
let isRefreshing = false;
let requests = [];

axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
axios.defaults.timeout = 6e4;
axios.defaults.retry = 1; //重试次数
axios.defaults.retryDelay = 0;//重试延时
axios.defaults.shouldRetry = (error) => true;//重试条件，默认只要是错误都需要重试

// token过期提示窗
const logModal = () => {
    Modal.confirm({
        title: '系统提示',
        content: '登录状态已过期，您可以继续留在该页面，或者重新登录',
        cancelText: '留在此页',
        okText: '重新登录',
        onOk: () => {
            store.dispatch('user/logOut').then(() => {
                location.href = '/'
            })
        }
    })
}


// axios.interceptors.response.use(res => {
//     const status = Number(res.status) || 200
//     if (status === 401) {
//         if (!isRefresh) {
//             isRefresh = true
//             return store.dispatch('RefreshToken', store.getters.refresh_token).then(data => {
//                 // 这里是去请求新的token 并返回promise 然后保存新的token
//                 store.commit('SET_ACCESS_TOKEN', data.data.access_token)
//                 store.commit('SET_REFRESH_TOKEN', data.data.refresh_token)
//                 res.config.headers['Authorization'] = data.data.access_token
//                 retryRequest.forEach(cb => {
//                     cb(data.data.access_token)
//                 })
//                 isRefresh = false
//                 retryRequest = []
//                 return axios(res.config)
//             })
//         } else {
//             return new Promise((resolve) => {
//                 // 将resolve放进队列，用一个函数形式来保存，等token刷新后直接执行
//                 retryRequest.push((token) => {
//                     res.config.headers['Authorization'] = token
//                     resolve(axios(res.config))
//                 })
//             })
//         }
//     }

// }

// 创建axios实例
const service = axios.create({
    baseURL: '/cipher'
});

// request拦截器
service.interceptors.request.use(config => {
    let key = md5(`${config.url}&${config.method}&${JSON.stringify(config.data)}`);
    config.cancelToken = new CancelToken(c => {
        if (pending[key]) {
            if (Date.now() - pending[key] > 1000) {
                // 超过1s，删除对应的请求记录，重新发起请求
                delete pending[key];
            } else {
                // 1s以内的已发起请求，取消重复请求
                c('repeated');
            }
        }
        //记录当前的请求，已存在则更新时间戳
        pending[key] = Date.now();
    });
    // 判断第一个token是否过期，如果过期使用备用token
    const tokens = config.url.includes('refreshToken') ? getCookie('tokens') : getCookie('token');
    if (tokens) {
        config.headers['Authorization'] = tokens // 让每个请求携带自定义token 请根据实际情况自行修改
    }
    // post请求处理无请求体
    if (config.method === 'post' && !config.data) config.data = '{}'
    // get请求映射params参数
    if (config.method === 'get' && config.params) {
        let url = config.url + '?'
        for (const propName of Object.keys(config.params)) {
            const value = config.params[propName]
            let part = encodeURIComponent(propName) + '='
            if (value !== null && typeof (value) !== 'undefined') {
                if (typeof value === 'object') {
                    for (const key of Object.keys(value)) {
                        let params = propName + '[' + key + ']'
                        let subPart = encodeURIComponent(params) + '='
                        url += subPart + encodeURIComponent(value[key]) + '&'
                    }
                } else {
                    url += part + encodeURIComponent(value) + '&'
                }
            }
        }
        url = url.slice(0, -1)
        config.params = {}
        config.url = url
    }
    return config
}, error => {
    console.error('err', error);
    console.dir(error);
    return Promise.reject(error);
});

// 响应拦截器
service.interceptors.response.use(res => {
    let key = md5(`${res.config.url.replace(/.*\/api/, '')}&${res.config.method}&${res.config.data}`);
    if (pending[key]) {
        // 请求结束，删除对应的请求记录
        delete pending[key];
    }
    // 未设置状态码则默认成功状态
    const code = res.data.status || 200
    const showMsg = res.config.showMsg ?? true;
    // 获取错误信息
    const msg = errorCode[code] || res.data.message || errorCode['default']
    if (code === 401) {
        if (res.config.url.includes('refreshToken')) logModal()
        else {
            //     if (!isRefreshing) {
            //         isRefreshing = true
            //         return store.dispatch('user/refreshToken').then(() => {
            //             var config = res.config;
            //             config.headers['Authorization'] = getCookie('token');
            //             if (!config || !config.retry) return Promise.reject(res);
            //             config.__retryCount = config.__retryCount || 0;

            //             if (config.__retryCount >= config.retry) {
            //                 return Promise.reject(res);
            //             }
            //             config.__retryCount += 1;
            //             var backoff = new Promise(function (resolve) {
            //                 setTimeout(function () {
            //                     resolve();
            //                 }, config.retryDelay || 1);
            //             });
            //             return backoff.then(function () {
            //                 return axios(config);
            //             });
            //             // })
            //         }).catch(() => logModal()).finally(() => isRefreshing = false);
            //     }
            // }
            const config = res.config
            if (!isRefreshing) {
                isRefreshing = true
                return store.dispatch('user/refreshToken').then(() => {
                    // debugger
                    let token = getCookie('token');
                    // service.setToken(token)
                    config.headers['Authorization'] = token;
                    // 已经刷新了token，将所有队列中的请求进行重试
                    requests.forEach(cb => cb(token))
                    requests = []
                    return service(config)
                }).catch(res => {
                    console.error('refreshtoken error =>', res)
                    logModal()
                }).finally(() => {
                    isRefreshing = false
                })
            } else {
                // 正在刷新token，返回一个未执行resolve的promise
                return new Promise((resolve) => {
                    // 将resolve放进队列，用一个函数形式来保存，等token刷新后直接执行
                    requests.push((token) => {
                        config.headers['Authorization'] = token;
                        resolve(service(config))
                    })
                })
            }
        }
    } else if (code !== 200) {
        showMsg && Message.error(msg);
        // showMsg && Message.error({
        //     content: msg,
        //     type: 'error',
        //     duration: 500 * 1000
        // });
        return Promise.reject(res.data);
    } else {
        return res.data;
    }
},
    error => {
        if (error.message == 'repeated') {
            return Promise.reject(new Error('数据正在处理，请勿重复提交'))
        } else {
            console.log('err' + error);
            console.dir(error);
            const showMsg = error.config.showMsg ?? true;
            let message = error.message;
            if (message === 'Network Error') {
                message = '后端接口连接异常'
            } else if (message.includes('timeout')) {
                message = '系统接口请求超时'
            } else if (message.includes('Request failed with status code')) {
                message = '系统接口' + message.substr(message.length - 3) + '异常'
            }
            showMsg && Message.error({
                content: message,
                duration: 5
            })
            router.replace({ path: "/login" });
        }
    }
)

// 通用下载方法
export function download(url, params, filename) {
    return service.post(url, params, {
        transformRequest: [(params) => {
            return tansParams(params)
        }],
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
        },
        responseType: 'blob'
    }).then((data) => {
        const blob = new Blob([data])
        if ('download' in document.createElement('a')) {
            const elink = document.createElement('a')
            elink.download = filename
            elink.style.display = 'none'
            elink.href = URL.createObjectURL(blob)
            document.body.appendChild(elink)
            elink.click()
            URL.revokeObjectURL(elink.href)
            document.body.removeChild(elink)
        } else {
            navigator.msSaveBlob(blob, filename)
        }
    }).catch((r) => {
        console.error(r)
    })
}

export default service
